package com.bsd.xxyp.rdlock.parse;

import com.bsd.xxyp.rdlock.annotation.LockBean;
import com.bsd.xxyp.rdlock.annotation.LockKey;
import com.bsd.xxyp.rdlock.context.LockAnnotationDataExtractor;
import com.bsd.xxyp.rdlock.exception.RdLockException;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author ：wangcheng
 * @date 2022/12/26
 **/
@Slf4j
public class LockAnnotationFieldParse {

    public List<String> parse(LockAnnotationDataExtractor extractor) {
        Method targetMethod = extractor.getTargetMethod();
        Object[] parameterValues = extractor.getParameterValues();
        Parameter[] parameters = targetMethod.getParameters();
        List<SortData> sortDataList = new ArrayList<>();
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            Object argValue = parameterValues[i];
            if (parameter.isAnnotationPresent(LockKey.class)) {
                LockKey annotation = parameter.getAnnotation(LockKey.class);
                sortDataList.add(getSortData(extractor, argValue, annotation.sort(), parameter.getName()));
            } else if (parameter.isAnnotationPresent(LockBean.class)) {
                Class<?> type = parameter.getType();
                while (!type.getTypeName().equals("java.lang.Object") && type !=null ) {
                    Field[] declaredFields = type.getDeclaredFields();
                    for (Field declaredField : declaredFields) {
                        if (declaredField.isAnnotationPresent(LockKey.class)) {
                            try {
                                declaredField.setAccessible(true);
                                Object o = declaredField.get(argValue);
                                LockKey annotation = declaredField.getAnnotation(LockKey.class);
                                sortDataList.add(getSortData(extractor, o, annotation.sort(), declaredField.getName()));
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    type = type.getSuperclass();
                }
            }
        }
        return sortDataList.stream().sorted(Comparator.comparing(SortData::getSort)).map(SortData::getValue).collect(Collectors.toList());
    }

    private SortData getSortData(LockAnnotationDataExtractor extractor, Object argValue, Integer sort, String fieldName) {
        SortData sortData = new SortData();
        sortData.setSort(sort);
        boolean blankFlag = false;
        if (argValue != null) {
            String argStr = String.valueOf(argValue);
            if (StringUtils.isNotBlank(argStr)) {
                sortData.setValue(argStr);
            }else {
                blankFlag = true;
            }
        } else {
            blankFlag = true;
            sortData.setValue(Strings.EMPTY);
        }

        if (blankFlag && !extractor.getRdLock().allowValueBlank()) {
            log.error("rdLock parse annotation fieldValueIsNull in: {} ,field name: {} "
                    , extractor.getClassSimpleName() + "#" + extractor.getMethodName(), fieldName);
            throw new RdLockException("rdLock业务key有空值");
        }

        return sortData;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    static class SortData{
        private Integer sort;
        private String value;
    }

    public static void main(String[] args) {
        System.out.println(null == "");
    }

}
